package cn.cxyxj.study06;

import cn.cxyxj.study06.email.EmailVerificationCodeAuthenticationFilter;
import cn.cxyxj.study06.email.EmailVerificationCodeAuthenticationProvider;
import cn.cxyxj.study06.email.EmailVerificationCodeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

/**
 * @author cxyxj
 */
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    MyAuthenticationSuccessHandler myAuthenticationSuccessHandler;

    @Autowired
    MyAuthenticationFailureHandler myAuthenticationFailureHandler;

    @Autowired
    private EmailVerificationCodeService emailVerificationCodeService;

    @Bean
    public EmailVerificationCodeAuthenticationFilter emailVerificationCodeAuthenticationFilter() throws Exception {
        EmailVerificationCodeAuthenticationFilter emailVerificationCodeAuthenticationFilter = new EmailVerificationCodeAuthenticationFilter();
        // 手动设置AuthenticationManager，解决authenticationManager must be specified 启动异常
        emailVerificationCodeAuthenticationFilter.setAuthenticationManager(authenticationManagerBean());
        emailVerificationCodeAuthenticationFilter.setAuthenticationSuccessHandler(new MyAuthenticationSuccessHandler());
        emailVerificationCodeAuthenticationFilter.setAuthenticationFailureHandler(new MyAuthenticationFailureHandler());
        return emailVerificationCodeAuthenticationFilter;
    }

    @Bean
    EmailVerificationCodeAuthenticationProvider emailVerificationCodeAuthenticationProvider() {
        EmailVerificationCodeAuthenticationProvider provider = new EmailVerificationCodeAuthenticationProvider(emailVerificationCodeService);
        return provider;
    }

    @Bean
    PasswordEncoder passwordEncoder() {
        return NoOpPasswordEncoder.getInstance();
    }
    @Bean
    @Override
    protected UserDetailsService userDetailsService() {
        InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
        manager.createUser(User.withUsername("cxyxj").password("123").roles("admin").build());
        manager.createUser(User.withUsername("security").password("security").roles("user").build());
        return manager;
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // 这行需要加上，否则请求参数需要带上 _csrf
        http.cors().and().csrf().disable();
        // 开启表单配置
        http.formLogin().permitAll();
        http.authorizeRequests()  //开启配置
                // 需要放行的接口路径
                .antMatchers().permitAll()
                .anyRequest() //其他请求
                .authenticated(); //验证   表示其他请求需要登录才能访问

       // 将邮箱身份验证过滤器放置在 UsernamePasswordAuthenticationFilter 之后
       http.addFilterAfter(emailVerificationCodeAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        // 设置 UserDetailsService 以及密码匹配器
        auth.userDetailsService(userDetailsService()).passwordEncoder(passwordEncoder());

        // 将自定义的 Provider 添加到 authenticationProviders 属性中
        auth.authenticationProvider(emailVerificationCodeAuthenticationProvider());
    }

}
